/*
 * ZonalLoop.java
 *
 * Created on February 28, 2005, 4:03 PM
 */

package edu.temple.GUS.MMA.Functions;
import edu.temple.GUS.MMA.DataTypes.*;
import edu.temple.GUS.MMA.Neighborhoods.*;
import edu.temple.GUS.MMA.Exceptions.MMAFunctionInitException;
import edu.temple.GUS.MMA.io.*;
import java.util.*;
import java.io.*;

/**
 *
 * @author  rkhanna
 */
public class ZonalLoop {
    
    /** Creates a new instance of ZonalLoop */
    public ZonalLoop() 
    {
    }
    
    public Hashtable loopTimeSeries_TimeSeries(MMATimeSeries tSeries1, MMATimeSeries tSeries2) throws MMAFunctionInitException
    {
        if ((tSeries1 == null) || (tSeries2 == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time series are not initialized.");

        // Ensure the time series have the identical dimensions
        if (tSeries1.getT() != tSeries2.getT())
            throw new MMAFunctionInitException(this.getClass().toString() + " Boundaries mismatch.");
        
        Hashtable ht = new Hashtable();
         for ( int i=0; i<tSeries1.getT(); i++)
        {
            Float key = new Float(tSeries1.getElement(i));
                       if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(tSeries2.getElement(i)));
                            ht.remove(key);                            
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(tSeries2.getElement(i));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
        }
         return ht;   
    }

    public Hashtable loopTimeSeries_TimeCube(MMATimeSeries tSeries, MMATimeCube tCube) throws MMAFunctionInitException
    {
        if ((tSeries == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time series not initialized.");

        if ((tCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time Cube not initialized.");
        
        // Ensure the time series have the identical dimensions
        if (tSeries.getT() != tCube.getT())
            throw new MMAFunctionInitException(this.getClass().toString() + " Boundaries mismatch.");
        
        Hashtable ht = new Hashtable();
         for ( int k=0; k<tSeries.getT(); k++)             
         {
            Float key = new Float(tSeries.getElement(k));
                for ( int j=0; j<tCube.getY(); j++)
                    for ( int i=0; i<tCube.getX(); i++)       
                    {    
                       if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(tCube.getElement(i,j,k)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(tCube.getElement(i,j,k));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
                    }  
         }
         return ht;   
    }
    

    public Hashtable loopTimeSeries_HyperCube(MMATimeSeries tSeries, MMAHyperCube hCube) throws MMAFunctionInitException
    {
        if ((tSeries == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time series not initialized.");

        if ((hCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Hyper Cube not initialized.");
        
        // Ensure the time series have the identical dimensions
        if (tSeries.getT() != hCube.getT())
            throw new MMAFunctionInitException(this.getClass().toString() + " Boundaries mismatch.");
        
        Hashtable ht = new Hashtable();
         for ( int l=0; l<tSeries.getT(); l++)             
         {
            Float key = new Float(tSeries.getElement(l));
                for ( int k=0; k<hCube.getZ(); k++)
                    for ( int j=0; j<hCube.getY(); j++)       
                        for ( int i=0; i<hCube.getX(); i++)                            
                        {    
                            if (ht.containsKey(key))
                            {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(hCube.getElement(i,j,k,l)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                            }	          
                            else
                            {
                            Float value = new Float(hCube.getElement(i,j,k,l));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                            }            
                    }  
         }
         return ht;   
    }

    
    public Hashtable loopGrid_Grid(MMAGrid grid1, MMAGrid grid2) throws MMAFunctionInitException        
    {
        if (( grid1 == null ) || ( grid2 == null ))
            throw new MMAFunctionInitException(this.getClass().toString() + " Grids are not initialized.");
        
        // Ensure the grids have the identical dimensions
        if ((grid1.getX() != grid2.getX()) || (grid1.getY() != grid2.getY()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); ;
        
        int x = grid1.getX();
        int y = grid1.getY();
        float noData = grid1.getNoData();
        
        Hashtable ht = new Hashtable();
        for ( int j=0; j<x; j++)
            for ( int i=0; i<y; i++)
            {    
                if (grid1.getElement(i,j)!=noData)
                {
                    Float key = new Float(grid1.getElement(i,j));
                        if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(grid2.getElement(i,j)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(grid2.getElement(i,j));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
                }
            }    
        
         return ht;   
    }
        
    public Hashtable loopGrid_TimeCube(MMAGrid grid, MMATimeCube tCube) throws MMAFunctionInitException        
    {
        if (grid == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Grid not initialized.");    
        
        if (tCube == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Time cube not initialized.");    
 

        // Ensure the time cubes have the identical dimensions
        if ((grid.getX() != tCube.getX()) || (grid.getY() != tCube.getY()) )
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 
      
        int x = tCube.getX();
        int y = tCube.getY();
        int t = tCube.getT();
        float noData = tCube.getNoData();
        
        Hashtable ht = new Hashtable();
        
            for ( int j=0; j<y; j++)
                for ( int i=0; i<x; i++)
                {    
                    if (grid.getElement(i,j)!=noData)
                    {
                        Float key = new Float(grid.getElement(i,j));
                        for ( int k=0; k<t; k++)
                        {    
                            if (ht.containsKey(key))
                            {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(tCube.getElement(i,j,k)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                            }	          
                            else
                            {
                            Float value = new Float(tCube.getElement(i,j,k));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                            }            
                        }    
                    }
                }    
        
         return ht;               
    }
    

    public Hashtable loopGrid_SpaceCube(MMAGrid grid, MMASpaceCube sCube) throws MMAFunctionInitException        
    {
            if (grid == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Grid not initialized.");    
        
        if (sCube == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Space cube not initialized.");    
 

        // Ensure the time cubes have the identical dimensions
        if ((grid.getX() != sCube.getX()) || (grid.getY() != sCube.getY()) )
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 
      
        int x = sCube.getX();
        int y = sCube.getY();
        int z = sCube.getZ();
        float noData = sCube.getNoData();
        
        Hashtable ht = new Hashtable();
            for ( int i=0; i<x; i++)
                for ( int j=0; j<y; j++)
                {    
                    if (grid.getElement(i,j)!=noData)
                    {
                        Float key = new Float(grid.getElement(i,j));
                        for ( int k=0; k<z; k++)
                        {    
                            if (ht.containsKey(key))
                            {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(sCube.getElement(i,j,k)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                            }	          
                            else
                            {
                            Float value = new Float(sCube.getElement(i,j,k));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                            }            
                        }
                    }     
                }    
        
         return ht;               
    }
         

    public Hashtable loopGrid_HyperCube(MMAGrid grid, MMAHyperCube hCube) throws MMAFunctionInitException        
    {
            if (grid == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Grid not initialized.");    
        
        if (hCube == null) 
            throw new MMAFunctionInitException(this.getClass().toString() + " Hyper cube not initialized.");    
 

        // Ensure the time cubes have the identical dimensions
        if ((grid.getX() != hCube.getX()) || (grid.getY() != hCube.getY()) )
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 
      
        int x = hCube.getX();
        int y = hCube.getY();
        int z = hCube.getZ();
        int t = hCube.getT();        
        float noData = hCube.getNoData();
        
        Hashtable ht = new Hashtable();
                for ( int i=0; i<x; i++)
                    for ( int j=0; j<y; j++)
                    {    
                        if (grid.getElement(i,j)!=noData)
                        {   
                            Float key = new Float(grid.getElement(i,j));
                            for ( int k=0; k<z; k++)
                                for ( int l=0; l<t; l++)
                                {    
                                    if (ht.containsKey(key))
                                    {	
                                    Vector temp = (Vector) ht.get(key);
                                    temp.add(new Float(hCube.getElement(i,j,k,l)));
                                    ht.remove(key);
                                    ht.put(key, temp );                            
                                    }	          
                                    else
                                    {
                                    Float value = new Float(hCube.getElement(i,j,k,l));
                                    Vector v = new Vector();
                                    v.add(value);
                                    ht.put(key, v);            
                                    }            
                                }   
                        }
                    }            
         return ht;               
    }

    
    public Hashtable loopSpaceCube_SpaceCube(MMASpaceCube sCube1, MMASpaceCube sCube2) throws MMAFunctionInitException        
    {
        if ((sCube1 == null) || (sCube2 == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Space cubes are not initialized.");    

        // Ensure the space cubes have the identical dimensions
        if ((sCube1.getX() != sCube2.getX()) || (sCube1.getY() != sCube2.getY()) || (sCube1.getZ() != sCube2.getZ()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); ;
        
        int x = sCube1.getX();
        int y = sCube1.getY();
        int z = sCube1.getZ();
        float noData = sCube1.getNoData();
        
        Hashtable ht = new Hashtable();
        for ( int k=0; k<z; k++)
            for ( int j=0; j<y; j++)
                for ( int i=0; i<x; i++)
                {    
                    if (sCube1.getElement(i,j,k)!=noData)
                    {
                        Float key = new Float(sCube1.getElement(i,j,k));
                        if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(sCube2.getElement(i,j,k)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(sCube2.getElement(i,j,k));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
                    }
                }    
        
         return ht;               
    }


    public Hashtable loopSpaceCube_HyperCube(MMASpaceCube sCube, MMAHyperCube hCube) throws MMAFunctionInitException        
    {
        if ((sCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Space cube not initialized.");    

        if ((hCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Hyper cube not initialized.");    

        // Ensure the space cubes have the identical dimensions
        if ((sCube.getX() != hCube.getX()) || (sCube.getY() != hCube.getY()) || (sCube.getZ() != hCube.getZ()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); ;
        
        int x = sCube.getX();
        int y = sCube.getY();
        int z = sCube.getZ();
        int t = hCube.getT();
        float noData = sCube.getNoData();

        
        Hashtable ht = new Hashtable();
        for ( int k=0; k<z; k++)
            for ( int j=0; j<y; j++)
                for ( int i=0; i<x; i++)
                {    
                    if (sCube.getElement(i,j,k)!=noData)
                    {
                        Float key = new Float(sCube.getElement(i,j,k));
                            for ( int l=0; l<t; l++)                                
                            {    
                                if (ht.containsKey(key))
                                {	
                                Vector temp = (Vector) ht.get(key);
                                temp.add(new Float(hCube.getElement(i,j,k,l)));
                                ht.remove(key);
                                ht.put(key, temp );                            
                                }	          
                                else
                                {
                                Float value = new Float(hCube.getElement(i,j,k,l));
                                Vector v = new Vector();
                                v.add(value);
                                ht.put(key, v);            
                                }            
                            }    
                    }
                }    
        
         return ht;               
    }
    
    
    public Hashtable loopTimeCube_TimeCube(MMATimeCube tCube1, MMATimeCube tCube2) throws MMAFunctionInitException        
    {
        if (( tCube1 == null) || ( tCube2 == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time cubes are not initialized.");    

        // Ensure the time cubes have the identical dimensions
        if ((tCube1.getX() != tCube2.getX()) || (tCube1.getY() != tCube2.getY()) || (tCube1.getT() != tCube2.getT()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 

      
        int x = tCube1.getX();
        int y = tCube1.getY();
        int t = tCube1.getT();
        float noData = tCube1.getNoData();

        
        Hashtable ht = new Hashtable();
        for ( int k=0; k<t; k++)
            for ( int j=0; j<y; j++)
                for ( int i=0; i<x; i++)
                {    
                    if (tCube1.getElement(i,j,k)!=noData)
                    {
                        Float key = new Float(tCube2.getElement(i,j,k));
                        if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(tCube2.getElement(i,j,k)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(tCube2.getElement(i,j,k));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
                    }
                }    
        
         return ht;               
    }


    public Hashtable loopTimeCube_HyperCube(MMATimeCube tCube, MMAHyperCube hCube) throws MMAFunctionInitException        
    {
        if (( tCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Time cube are not initialized.");    

        if (( hCube == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Hyper cube are not initialized.");    

        // Ensure the time cubes have the identical dimensions
        if ((tCube.getX() != hCube.getX()) || (tCube.getY() != hCube.getY()) || (tCube.getT() != hCube.getT()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 

      
        int x = tCube.getX();
        int y = tCube.getY();
        int z = hCube.getZ();        
        int t = tCube.getT();
        float noData = tCube.getNoData();

        
        Hashtable ht = new Hashtable();
        for ( int l=0; l<t; l++)
            for ( int j=0; j<y; j++)
                for ( int i=0; i<x; i++)
                {    
                    if (tCube.getElement(i,j,l)!=noData)
                    {
                        Float key = new Float(tCube.getElement(i,j,l));
                            for ( int k=0; k<z; k++)
                            {    
                                if (ht.containsKey(key))
                                {	
                                Vector temp = (Vector) ht.get(key);
                                temp.add(new Float(hCube.getElement(i,j,k,l)));
                                ht.remove(key);
                                ht.put(key, temp );                            
                                }	          
                                else
                                {
                                Float value = new Float(hCube.getElement(i,j,k,l));
                                Vector v = new Vector();
                                v.add(value);
                                ht.put(key, v);            
                                }
                            }            
                       }
                    }    
        
         return ht;               
    }
    
    
    public Hashtable loopHyperCube_HyperCube(MMAHyperCube hCube1, MMAHyperCube hCube2) throws MMAFunctionInitException        
    {
        if ((hCube1 == null) || (hCube2 == null))
            throw new MMAFunctionInitException(this.getClass().toString() + " Hyper cubes are not initialized.");    

        // Ensure the hyper cubes have the identical dimensions
        if ((hCube1.getX() != hCube2.getX()) || (hCube1.getY() != hCube2.getY()) || (hCube1.getZ() != hCube2.getZ()) || (hCube1.getT() != hCube2.getT()))
            throw new MMAFunctionInitException(this.getClass().toString() +  " Boundaries mismatch."); 
            
   
        int x = hCube1.getX();
        int y = hCube1.getY();
        int z = hCube1.getZ();
        int t = hCube1.getT();
        float noData = hCube1.getNoData();

        
        Hashtable ht = new Hashtable();
        for ( int l=0; l<t; l++)
            for ( int k=0; k<z; k++)
                for ( int j=0; j<y; j++)
                    for ( int i=0; i<x; i++)
                    {    
                        if (hCube1.getElement(i,j,k,l)!=noData)
                        {
                        Float key = new Float(hCube1.getElement(i,j,k,l));
                        if (ht.containsKey(key))
                        {	
                            Vector temp = (Vector) ht.get(key);
                            temp.add(new Float(hCube2.getElement(i,j,k,l)));
                            ht.remove(key);
                            ht.put(key, temp );                            
                        }	          
                        else
                        {
                            Float value = new Float(hCube2.getElement(i,j,k,l));
                            Vector v = new Vector();
                            v.add(value);
                            ht.put(key, v);            
                        }            
                        }
                    }    
        
            /*Enumeration e = ht.keys();
            while (e.hasMoreElements())
            {
                Float ff = (Float)e.nextElement();                
                float outputkey = ff.floatValue();
                float outputvalue = ((Float)ht.get(ff)).floatValue();               
                System.out.println(outputkey + ":::" + outputvalue);
            } */        
         return ht;               
    }
    
}
